#pragma once

#include <QtGui>
#include <fstream>

// http://lists.trolltech.com/qt-interest/2005-06/thread00166-0.html
// http://www.qtforum.de/forum/viewtopic.php?t=7970

class QDebugStream : public QObject, std::basic_streambuf<char>{

	Q_OBJECT

signals:
	void sendString(QString text);
	
                 
public:
	std::ofstream cons;
	QDebugStream(std::ostream &stream, QPlainTextEdit* text_edit) : m_stream(stream)
	{
		log_window = text_edit;
		m_old_buf = stream.rdbuf();
		stream.rdbuf(this);
		cons.open ("console");
		connect(this, SIGNAL(sendString(QString)), text_edit, SLOT(appendPlainText(QString)));
	}
	~QDebugStream(){
		// output anything that is left
		if (!m_string.empty())
		{
			emit sendString(m_string.c_str());
		}
		//log_window->appendPlainText(m_string.c_str());
		cons.close();
		m_stream.rdbuf(m_old_buf);
	}

protected:
	virtual int_type overflow(int_type v)
	{
		mutex.lock();
		if (v == '\n')
		{
			emit sendString(m_string.c_str());
				this->cons << m_string << "\n";
			//log_window->appendPlainText(m_string.c_str());
			m_string.erase(m_string.begin(), m_string.end());
		}
		else
		{
			m_string += v;
		}

		mutex.unlock();
		return v;
	}

	virtual std::streamsize xsputn(const char *p, std::streamsize n)
	{
		mutex.lock();

		m_string.append(p, p + n);
		int pos = 0;
		while (pos != std::string::npos)
		{
			pos = m_string.find('\n');
			if (pos != std::string::npos)
			{
				std::string tmp(m_string.begin(), m_string.begin() + pos);
				emit sendString(tmp.c_str());
				
				this->cons << tmp << "\n";
				//log_window->appendPlainText(tmp.c_str());
				m_string.erase(m_string.begin(), m_string.begin() + pos + 1);
			}
		}

		mutex.unlock();
		return n;
	}

private:
	std::ostream &m_stream;
	std::streambuf *m_old_buf;
	std::string m_string;
	QPlainTextEdit* log_window;
	QMutex mutex;
};
